#!/usr/bin/python
# -*- coding: utf-8 -*-
import urllib
import datetime
import hashlib
import hmac
import urllib2
from handler import Tango
import invhero.log
import decorators
from decimal import Decimal
import traceback
import uuid
import json
import base64
from invhero.mercury import mercury
from invhero.exceptions import*
from Crypto.Hash import MD5
import invhero.utils.send
from urllib import quote
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
logger=logging.getLogger(__name__)

#商户密钥
MD5Key = "Zpv4M9Jc8jZz2nuonl5H4mbgpTnyey"

# 生成签名
def generate_sign(params):
 try:
  keys = sorted(params.keys())
  post_str = ''
  for key in keys:
   post_str += key.replace('res_','') + '=>' + str(params[key]) + '&'
  post_str += 'key=' + MD5Key
  signature = MD5.new(post_str).hexdigest().upper()
  return signature
 except Exception:
  logger.error('[BSJ入金接口]生成签名失败, %s', traceback.format_exc())
  return ''

class RealDepositBSJHandler(Tango):

 @decorators.auth_access
 def post(self,*args,**kwargs):
  #验证用户
  wl=self.user.wl
  if wl!='':
   whitelabel=invhero.whitelabel.WhitelabelCollection.get_one_by_codename(wl)
   if not whitelabel:
    raise IHStandardError(1600,'找不到公司配置')
   if int(whitelabel.get('deposit_enabled',1))==0:
    raise IHStandardError(1606,'当前不允许入金')

  user_id=str(self.user.id)
  amount=self.get_argument('amount')
  #验证充值金额
  try:
   amount=Decimal(amount)
  except Exception,e:
   raise IHStandardError(400,'金额参数不是有效的数字')
  min_deposit=invhero.whitelabel.get_whitelabel_deposit_min(wl)
  if amount<Decimal(min_deposit):
   raise IHStandardError(400,'充值金额小于最低入金金额%s'%min_deposit)

  #支付基本参数
  pay_memberid = '10045'
  tjurl = "http://www.bsj888.cn/Pay_Index.html"
  pay_notifyurl = invhero.SERVICE_URL.get('callback')+'/v1/user/pay/deposit_bsj/notify'
  pay_callbackurl = 'http://wt-ifbao.if138.com/ifbao/s/webtrade/trade.html'
  # tongdao = 'HXWY'
  tongdao = 'KHWY'
  # pay_bankcode = 'ICBC'
  pay_bankcode = self.get_argument('bankCode')

  #获得时间、金额、汇率
  time = datetime.datetime.now()
  account=invhero.account.get_account_by_uid(self.user.id,'real')
  usdcny_rate=invhero.config.get_deposit_withdraw_usdcny_rate(self.user.wl)

  #转换成人民币、生成订单
  cnh_amount=str(round(float(amount)*usdcny_rate['deposit'],2))
  order_no = time.strftime('%Y%m%d')+'-'+user_id+'-'+time.strftime('%H%M%S')

  #插入存根
  insert_data={'user_id': account.user_id,'pay_status': '0','confirm_status' :'0','amount':amount,'created':time,
               "pay_memberid": pay_memberid,
               "pay_orderid": order_no,
               "pay_amount": cnh_amount,
               "pay_applydate": time.strftime('%Y-%m-%d %H:%M:%S'),
               "pay_bankcode": pay_bankcode,
               "pay_notifyurl": pay_notifyurl,
               "pay_callbackurl": pay_callbackurl,
               'tongdao' : tongdao
               }
  try:
   invhero.models.Collection.insert(insert_data,table_name='deposit_BSJ')
  except Exception:
   logger.error('向deposit_BSJ表中添加入金存根失败, %s',traceback.format_exc())
   self.out.status=500
   self.out.message=u'添加入金存根失败'
   self.out.data=traceback.format_exc()
   return
  logger.warning('[BSJ入金接口]生成入金存根， %s' % str({'post_data': insert_data}))

  #设置请求体
  post_data = {
   "pay_memberid": insert_data['pay_memberid'],
   "pay_orderid": insert_data['pay_orderid'],
   "pay_amount": insert_data['pay_amount'],
   "pay_applydate": insert_data['pay_applydate'],
   "pay_bankcode": insert_data['pay_bankcode'],
   "pay_notifyurl": insert_data['pay_notifyurl'],
   "pay_callbackurl": insert_data['pay_callbackurl'],
  }

  #签名
  signature = generate_sign(post_data)
  if signature == '':
   self.out.status = 500
   self.out.message = u'生成签名失败'
   return
  post_data['pay_md5sign'] = signature
  post_data['tongdao'] = tongdao

  logger.warning('[BSJ入金接口]生成银行支付请求信息， %s' % str(signature))

  #返回BSJ访问地址
  self.out.status = 200
  self.out.data = {'post_url':tjurl, 'post_data': json.dumps(post_data)}
  return

class RealDepositBSJBackHandler(Tango):
 def get(self,*args,**kwargs):
  req=self.request.arguments
  self.out.status = 200
  self.out.data = {'post_url': 123, 'post_data': 4}
  self.write(str(req))

  return
  logger.warning('get RealDepositBSJBackHandler back :%s'%str(req))

class RealDepositBSJNotifyHandler(Tango):

 def get(self,*args,**kwargs):

  req = self.request.arguments

  logger.warning('[BSJ入金接口]第三方异步响应信息，%s' % str(req))

  res_memberid = self.get_argument('memberid')
  res_orderid = self.get_argument('orderid')
  res_amount = self.get_argument('amount')
  res_datetime = self.get_argument('datetime')
  res_returncode = self.get_argument('returncode')
  res_sign = self.get_argument('sign')

  res_data = {
   'res_memberid' : res_memberid,
   'res_orderid': res_orderid,
   'res_amount': res_amount,
   'res_datetime': res_datetime,
   'res_returncode': res_returncode,
  }

  if (res_data['res_returncode'] != '00'):
   self.write('errpr')
   return

  #验签
  signature = generate_sign(res_data)

  #记录返回值
  if res_sign == signature:
   #查询入金存根
   # v_oid = res_v_orderNumber
   rows=invhero.models.Collection.query(table_name='deposit_BSJ',where='pay_orderid = %(pay_orderid)s',where_value={'pay_orderid':res_data['res_orderid']})

   if int(rows[0]['pay_status'])!=0:
    logger.warning('[BSJ入金接口]查询入金存根 , res_orderid: %s'%res_data['res_orderid'])
    self.write('error')
    return
   user_id = rows[0]['user_id']
   account = invhero.account.get_account_by_uid(user_id,'real')
   new_update_data={'pay_status':0,'confirm_status':1}
   for key in res_data.keys():
    new_update_data[key] = res_data[key]

   # 支付状态,支付成功更新账户
   trade_status = new_update_data['res_returncode']
   if trade_status == '00':
    new_update_data['pay_status']=1
    self.deposit_success_update_data(new_update_data,account,rows[0]['amount'])
    self.write('ok')
    return
  else:
   self.write = 'error'
   return

 #更新入金
 def deposit_success_update_data(self,new_update_data,account,amount):
  #(insert_data_keys)的数据需要插入到deposit_BSJ和transaction_log中
  #（new_update_data）的数据用来更新deposit_BSJ
  #生成transaction_log表的数据

  clordid=str(uuid.uuid4())
  insert_data={'user_id':account.user_id,'broker_account':account.broker_account,
               'action':'deposit','amount':amount,
               'balance':account.balance,'buyer_ip':'',
               'equity':account.equity,'credit':account.credit,
               'clordid':clordid,'confirmed':0,
               'post_url':'','post_data':'',
               'created':datetime.datetime.now(),'reason':'801',
               'context':'','paid_through':'deposit_BSJ',
               'account_mode':account.mode}
  logger.warning('[BSJ入金接口]transaction_log的insert_data: %s'%str(insert_data))
  tx_conn=invhero.DB_CONN_TRANSACTION

  try:
   #插入数据
   insert_data_keys=insert_data.keys()
   insert_keys,insert_values=','.join(['%s'%key for key in insert_data_keys]),','.join(['%%(%s)s'%key for key in insert_data_keys])
   #transaction_log生成的ID
   transaction_log_id=tx_conn.insert('insert into transaction_log(%s) values(%s);'%(insert_keys,insert_values),**insert_data)
   logger.warning('[BSJ入金接口]向transaction_log加入一条记录, id: %d'%transaction_log_id)
   #更新deposit_BSJ的数据（支付成功、transaction_log的ID）
   new_update_data['pay_status']=1
   new_update_data['transaction_log_id']=transaction_log_id
   web_update_keys=new_update_data.keys()
   sql='update deposit_BSJ set %s where pay_orderid = %%(pay_orderid)s;'%','.join(['%s=%%(%s)s'%(key,key)for key in web_update_keys])
   logger.warning(sql)

   try:
    tx_conn.update(sql,pay_orderid=new_update_data['res_orderid'],**new_update_data)
   except Exception:
    logger.error('[BSJ入金接口]事务出错',traceback.format_exc())

    tx_conn.rollback()
    raise
   logger.warning('[BSJ入金接口]更新存根支付状态为支付完成')

   try:
    tx_conn.commit()
   except Exception:
    logger.error('[BSJ入金接口]事务提交失败: %s',traceback.format_exc())
    raise

   #入金并更新数据库（通用）
   withdrawable_notional_threshold = amount*mercury.DEPOSIT_TRIGGER_RATIO
   mercury_deposit_response = mercury.do_deposit_withdraw(account.broker_server,account.broker_account,clordid,str(amount),mercury.DEPOSIT_TYPE_NORMAL,'',str(withdrawable_notional_threshold))
   logger.warning('[boapy入金接口]向mercury入金, deposit_data: %s'%mercury_deposit_response)
   package,response,result=mercury_deposit_response.get('package'),None,None
   result=mercury_deposit_response.get('result')
   if result=='0':
    update_ok,error_message=account.update_mercury_deposit_data(mercury_deposit_response,insert_data,action='deposit')
    if update_ok:
     user=invhero.user.get_user_by_uid(account.user_id)
     deposit_bonus_ok,deposit_bonus_amount,error_message=account.mercury_deposit_bonus(user,insert_data)
     if deposit_bonus_ok:
      send_mail_notification(pay_channel=u'百盛嘉支付',broker_account=account.broker_account,amount=amount,merOrderId=new_update_data['res_orderid'],deposit_status=u'成功',extra=u'支付通道应答：%s\r\n赠金：%s'%(new_update_data['res_returncode'],deposit_bonus_amount))
     else:
      send_mail_notification(pay_channel=u'百盛嘉支付',broker_account=account.broker_account,amount=amount,merOrderId=new_update_data['res_orderid'],deposit_status=u'成功',extra=u'支付通道应答：%s\r\n赠金：%s\r\n入赠金失败：%s'%(new_update_data['res_returncode'],deposit_bonus_amount,error_message))
    else:
     send_mail_notification(pay_channel=u'百盛嘉支付',broker_account=account.broker_account,amount=amount,merOrderId=new_update_data['res_orderid'],deposit_status=u'失败',extra=u'MECURY入金成功！更新数据库失败：%s'%error_message)
   else:
    send_mail_notification(pay_channel=u'百盛嘉支付',broker_account=account.broker_account,amount=amount,merOrderId=new_update_data['res_orderid'],deposit_status=u'失败',extra=u'MECURY入金失败！mercury应答：result：%s'%result)
  except Exception:
   try:
    logger.error('[BSJ入金接口]更新数据库失败 %s',traceback.format_exc())
    tx_conn.rollback()
   except Exception:
    logger.error('[BSJ入金接口]更新数据库失败，rollback失败 %s',traceback.format_exc())
def send_mail_notification(pay_channel=u'百盛嘉支付',broker_account=u'',amount=u'',merOrderId=u'',deposit_status=u'',extra=u''):
 try:
  subject=u'[%s] 账户%s 入金%s %s'%(pay_channel,broker_account,amount,deposit_status)
  body=u'账户：%s\r\n入金金额：%s\r\n商户号：%s\r\n入金来源：%s\r\n状态：%s\r\n%s'%(broker_account,amount,merOrderId,pay_channel,deposit_status,extra)
  send_mail(invhero.DEPOSIT_MAIL_RECEIVERS,subject,body.encode('utf-8'))
 except Exception:
  # try:
  #  f = open('/data/webapps/invhero_deposit/api/handlers/testbsj.txt', 'a')
  #  f.write('sendMailError:')
  #  f.write(str(traceback.format_exc()))
  #  f.write('\r\n\r\n')
  #  f.close()
  # finally:
  #  if f:
  #   f.close()
  logger.error('failed send mail (deposit): %s',traceback.format_exc())
def send_mail(receivers,subject,body):
  mail_sender=invhero.MAIL_SENDER
  login=mail_sender.get('login')
  password=mail_sender.get('password')
  server='smtp.qq.com'
  if login.find('xinwaihui.com')!=-1:
   server='smtp.exmail.qq.com'
  msg=MIMEMultipart('alternative')
  msg['Subject']=subject
  msg['From']=login
  msg['To']=','.join(receivers)
  msg_html_part=MIMEText(body,'html')
  msg.attach(msg_html_part)
  s=smtplib.SMTP_SSL(server,port=465)
  s.login(login,password)
  s.sendmail(login,receivers,msg.as_string())
